home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 52
/
Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso
/
Aminet
/
misc
/
emu
/
Apex-src.lha
/
TRANSCND.XPL
< prev
next >
Wrap
Text File
|
2001-09-30
|
9KB
|
425 lines
\TRANSCND.XPL OCT-28-86
code
ABS=0, RAN=1, REM=2, RESERVE=3,
SWAP=4, EXTEND=5, RESTART=6, CHIN=7,
CHOUT=8, CRLF=9, INTIN=10, INTOUT=11,
TEXT=12, OPENI=13, OPENO=14, CLOSE=15,
FIX=50, HEXOUT=27;
code real RLRES=46, FLOAT=49, RLABS=51;
int II, JJ, M, N, MDIGIT;
real XX, YY, AA, BB;
\def PI= 3.1415926535897932, \\PI
\ PI2= 6.2831853071795864, \\PI *2
\ HALFPI= 1.5707963267948966, \\PI /2
\ HALFPI3= 4.7123889803846898; \\PI /2 *3
real PI, PI2, HALFPI, HALFPI3;
func real SQRT(X); \SQUARE ROOT FUNCTION
real X;
real G1, G2;
int EXP, I;
addr A, A2;
begin
if X < 0.0 then X:= -X; \ERROR: SQUARE ROOT OF A NEGATIVE NUMBER
A:= addr X;
EXP:= SWAP(A(0)) + A(1);
EXP:= EXP /2 + $1FF8;
A2:= addr G1;
G1:= 2.0;
A2(0):= SWAP(EXP); A2(1):= EXP;
for I:= 0,6 do
begin
G2:= X /G1;
G1:= (G1 + G2);
G1:= G1 /2.0;
if G1 = G2 then I:= 1000;
end;
return G1;
end; \SQRT
func real MOD(X, Y); \MODULO FUNCTION
\E.G: MOD(10.0, 3.0) = 1.0; MOD(-12.3, 1.0) = -0.3
\WARNING: THIS ROUTINE LOSES PRECISION AS RESULT APPROACHES 0.0
\ ALSO, ATTEMPTING TO GET MODULOS BEYOND 32 BITS OF PRECISION CAUSES
\ A FIX OVERFLOW.
real X, Y;
real Z;
begin
Z:= X /Y -0.5;
return X - FLOAT(FIX(Z)) *Y;
end; \MOD
func real POLLY(X, P, N);
\EVALUATE X USING A POLYNOMIAL EXPRESSION OF THE FORM:
\ = P0 + P1 *X^2 + P2 *X^4 + P3 *X^6
\ = (((P3 *X^2) + P2) *X^2 + P1) *X^2 + P0
real X, \NUMBER TO APPROXIMATE
P; \TABLE OF COEFFICIENTS
int N; \NUMBER OF TERMS
int I; \LOOP COUNTER
real X2; \X^2, X SQUARED
begin
X2:= X *X;
X:= P(N-1);
for I:= -(N-2), 0 do
X:= X *X2 + P(-I);
return X;
end; \POLLY
func real COS(X); \RETURN THE COSINE OF X
real X;
real P;
begin
\REDUCE RANGE TO 0 <= X < HALFPI
X:= RLABS(X);
if X>PI2 then X:= MOD(X,PI2);
P:=[ 0.9999999999999999960897E+00,
-0.49999999999999974308584E+00,
0.4166666666666387895916E-01,
-0.138888888887731721151E-02,
0.24801587277443938629E-04,
-0.275573163935346178E-06,
0.20876561960112253E-08,
-0.114629048993344E-10,
0.46090073769E-13];
if X<HALFPI then \QUADRANT 1
return if X<1E-10 then 1.0 else POLLY(X, P, 9);
if X<HALFPI3 then return -POLLY(X-PI, P, 9); \QUADRANTS 2 OR 3
return POLLY(PI2-X, P, 9); \QUADRANT 4
end; \COS
func real SIN(X); \RETURN THE SINE OF X
real X;
begin
return if RLABS(X) < 1E-5 then X else COS(HALFPI -X);
end; \SIN
func real TAN(X); \RETURN THE TANGENT OF X
real X;
real Y, Z;
begin
Y:= SIN(X);
Z:= COS(X);
return Y /Z;
end; \TAN
func real ATAN(X); \ARC-TANGENT FUNCTION
real X;
real P,
ATAN25,
ATAN75;
func real ATANY(X); \ARC-TANGENT FUNCTION FOR 0.0 >= X < 1.0
real X;
real Z;
begin
if X >= 0.5 then
begin
Z:= (X -0.75) /(1.0 + X *0.75);
X:= POLLY(Z, P, 9) *Z + ATAN75;
end
else begin
Z:= (X -0.25) /(1.0 + X *0.25);
X:= POLLY(Z, P, 9) *Z + ATAN25;
end;
return X;
end; \ATANY
func real ATANX(X); \ARC-TANGENT FUNCTION FOR POSITIVE X
real X;
begin
return if X >= 1.0 then HALFPI -ATANY(1.0/X) else ATANY(X);
end; \ATANX
begin
ATAN25:= 0.244978663126864154;
ATAN75:= 0.643501108793284386;
P:= [ 0.9999999999999999849899E+00,
-0.333333333333299308717E+00,
0.1999999999872944792E+00,
-0.142857141028255452E+00,
0.11111097898051048E+00,
-0.909037114191074E-01,
0.767936869066E-01,
-0.6483193510303E-01,
0.443895157187E-01];
return if X < 0.0 then -ATANX(-X) else ATANX(X);
end; \ATAN
func real ATAN2(Y,X); \RETURN THE ARCTANGENT OF Y/X
real Y, X;
begin
if X = 0.0 then return HALFPI *Y /RLABS(Y);
if X > 0.0 then
return ATAN(Y/X)
else return if Y >= 0.0 then ATAN(Y/X) + PI else ATAN(Y/X) - PI;
end; \ATAN2
func real ASIN(X); \ARC-SINE FUNCTION
\WARNING: INACCURATE AS RLABS(X) APPROACHES 1.0.
real X;
real Z;
begin
Z:= SQRT(1.0 - X *X);
return ATAN(X /Z);
end; \ASIN
func real ACOS(X); \ARC-COSINE FUNCTION
\WARNING: INACCURATE AS RLABS(X) APPROACHES 1.0.
real X;
real Z;
begin
return -ASIN(X) + HALFPI;
end; \ACOS
proc FORMAT(M1, N1); \SET FORMAT PARAMETERS FOR RLOUT
int M1, N1;
begin
MDIGIT:= M1;
N:= N1;
end; \FORMAT
proc RLOUT(DEV, X);
\Output the real number X to the specified device.
\Other inputs: M, N.
int DEV;
real X;
real SX, RND, HALF, ONE, TEN;
int I, K, L, NEG;
def SIGFIGS =15; \Maximum number of decimal digits
proc DIGITOUT;
int DIGIT;
begin
for I:= 1, K do
begin
if L > 0 then
begin
X:= X *TEN;
DIGIT:= FIX(X -HALF);
CHOUT(DEV, DIGIT +^0);
X:= X -FLOAT(DIGIT);
L:= L -1;
end
else CHOUT(DEV,^0);
end;
end; \DIGITOUT
begin
TEN:= FLOAT(10);
ONE:= FLOAT(1);
HALF:= ONE /FLOAT(2);
if X < FLOAT(0) then [X:= -X; NEG:= true] else NEG:= false;
K:= 0;
SX:= X; \SAVE ORIGINAL NUMBER TO DETERMINE LEADING ZERO
if X # FLOAT(0) then
begin
while X >= ONE do [X:= X /TEN; K:= K +1];
\ADD IN ROUNDING FACTOR: 0.5 * 10 ^ -(K+N)
RND:= HALF;
L:= K +N;
if L > SIGFIGS then L:= SIGFIGS;
for I:= 1, L do RND:= RND /TEN;
X:= X +RND;
if X >= ONE then
[X:= X /TEN; K:= K +1; \ADJUST FOR ROUND OVERFLOW
SX:= TEN]; \FORGET ABOUT LEADING ZERO
end;
\Calculate the number of leading blanks needed:
L:= M -K;
if SX < ONE then L:= L-1; \LEAVE ROOM FOR LEADING ZERO
for I:= 1, L do CHOUT(DEV,^ );
CHOUT(DEV, if NEG then ^- else ^ );
if SX < ONE then CHOUT(DEV,^0); \OUTPUT LEADING ZERO, E.G: 0.2
L:= SIGFIGS;
DIGITOUT; \OUTPUT DIGITS IN FRONT OF THE D.P.
if N > 0 then [CHOUT(DEV,^.); K:= N; DIGITOUT]; \OUTPUT DIGITS AFTER D.P.
end; \RLOUT
proc RLOUTX(DEV, X);
\Output the real number X to the specified device.
\Other inputs: MDIGIT, N.
int DEV;
real X;
int NEG, EXP;
real ZERO, ONE, TEN, KILO;
proc EXPOUT;
begin
if NEG then X:= -X;
RLOUT(DEV, X);
CHOUT(DEV, ^E);
CHOUT(DEV, if EXP < 0 then ^- else ^+);
EXP:= ABS(EXP);
if EXP < 10 then CHOUT(DEV, ^0);
INTOUT(DEV, EXP);
end; \EXPOUT
begin
if MDIGIT > 1 then [M:= MDIGIT; RLOUT(DEV, X); return];
ZERO:= FLOAT(0);
ONE:= FLOAT(1);
TEN:= FLOAT(10);
KILO:= FLOAT(1000);
if X < ZERO then [X:= -X; NEG:= true] else NEG:= false;
EXP:= 0;
if MDIGIT = 0 then \SCIENTIFIC NOTATION
begin \E.G: 1.2E+23, 1.2E-102, 1.2E+02
M:= 2;
if X # ZERO then
begin
while X < ONE do [X:= X *TEN; EXP:= EXP -1];
while X >= TEN do [X:= X /TEN; EXP:= EXP +1];
end;
EXPOUT;
end
else begin \ENGINEERING NOTATION
M:= 4;
if X # ZERO then
begin
while X < ONE do [X:= X *KILO; EXP:= EXP -3];
while X >= KILO do [X:= X /KILO; EXP:= EXP +3];
end;
EXPOUT;
end;
end; \RLOUTX
func real RLIN(DEV);
\Read in the ASCII representation of a real number from the specified device
\ and return its value.
int DEV; \Input device
int CH, \Character
EX, \Power-of-ten exponent, total effective value
N, \Exponent as specified by input
NEG, \Flag: Negative real number
ENEG, \Flag: Negative exponent
DIGIT; \Flag: Last character is a digit (0 thru 9)
real X, \Value of real number
TEN; \1.0, Avoids use of real constants which are not as easily
\ ported from one floating point representation to another.
proc GETCH; \Get character from input device
begin
CH:= CHIN(DEV);
DIGIT:= CH>=^0 & CH<=^9; \Is it a digit?
end; \GETCH
proc ADDIN;
begin
X:= X *TEN + FLOAT(CH -^0);
end; \ADDIN
begin \RLIN
TEN:= FLOAT(10);
NEG:= false;
loop begin
GETCH; \Ignore any leading garbage
if CH =^- then NEG:= not NEG;
if DIGIT then
begin
X:= FLOAT(CH -^0);
loop begin
GETCH;
if not DIGIT then quit;
ADDIN;
end;
quit;
end;
if CH=^. then [X:= FLOAT(0); quit];
end;
EX:= 0;
if CH = ^. then
loop begin
GETCH;
if not DIGIT then quit;
ADDIN;
EX:= EX -1; \if X gets bigger, the exponent gets smaller
end;
if CH=^E ! CH=^e then
begin
N:=0;
GETCH;
if CH = ^- then [ENEG:= true; GETCH] else ENEG:= false;
if CH = ^+ then GETCH;
while DIGIT do [N:= N *10 +(CH -^0); GETCH];
EX:= EX + (if ENEG then -N else N);
end;
while EX < 0 do [X:= X /TEN; EX:= EX +1];
while EX > 0 do [X:= X *TEN; EX:= EX -1];
return if NEG then -X else X;
end; \RLIN
begin \MAIN
\DEFINED CONSTANTS DON'T WORK
PI:= 3.1415926535897932;
PI2:= 6.2831853071795864;
HALFPI:= 1.5707963267948966;
HALFPI3:= 4.7123889803846898;
loop begin
FORMAT(0,10);
YY:= RLIN(0);
XX:= RLIN(0);
YY:= ATAN2(YY,XX);
RLOUTX(0,YY); CRLF(0);
end;
end; \MAIN
loop begin
FORMAT(0,10)